package com.itheima.reggie.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.entity.Page;
import com.itheima.reggie.exception.CustomException;
import com.itheima.reggie.mapper.CategoryMapper;
import com.itheima.reggie.mapper.DishFlavorMapper;
import com.itheima.reggie.mapper.DishMapper;
import com.itheima.reggie.service.DishService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class DishServiceImpl implements DishService {
    @Autowired(required = false)
    private DishMapper dishMapper;
    @Autowired(required = false)
    private DishFlavorMapper dishFlavorMapper;
    @Autowired(required = false)
    private CategoryMapper categoryMapper;
    @Autowired(required = false)
    private RedisTemplate redisTemplate;

    //保存添加菜品信息
    @Override
    @Transactional//开启事务
    public void saveWithFlavor(DishDto dishDto) {
        //给菜品补全菜品添加时间，修改时间
        dishDto.setCreateTime(LocalDateTime.now());
        dishDto.setUpdateTime(LocalDateTime.now());
        dishDto.setSort(0);
        dishDto.setStatus(1);
        //保存菜品
        dishMapper.save(dishDto);//学习mybatis的时候，保存数据可以让主键列设置给当前的实体类对象
        //获取所有口味信息
        List<DishFlavor> flavors = dishDto.getFlavors();
        //遍历所有口味信息，补全dish_id 、 创建时间、修改时间、创建人、修改人、
        //使用JDK8新特性，stream，map映射
        List<DishFlavor> dishFlavorList = flavors.stream().map((flavor -> {
            //対每位元素进行加工
            flavor.setDishId(dishDto.getId());
            flavor.setCreateTime(LocalDateTime.now());
            flavor.setUpdateTime(LocalDateTime.now());
            flavor.setCreateUser(dishDto.getCreateUser());
            flavor.setUpdateUser(dishDto.getUpdateUser());
            return flavor;
        })).collect(Collectors.toList());
        //批量保存口味信息
        dishFlavorMapper.saveBatch(dishFlavorList);
        //菜品发生变化，需要清理缓存
        Set keys = redisTemplate.keys("dish_*");
        redisTemplate.delete(keys);
    }

    //菜品分页，模糊查询
    @Override
    public Page<DishDto> page(Integer page, Integer pageSize, String name) {
        //1. 设置当前页与页面大小
        PageHelper.startPage(page, pageSize);
        //2. 查询数据，这里得到的是List<Dish>
        List<Dish> dishList = dishMapper.findByName(name);
        //3. 得到PageInfo,pageINfo对象里面存储的是Dish.
        PageInfo<Dish> pageInfo = new PageInfo<>(dishList);
        //4. 得到分页数据的集合，然后遍历所有的Dish，然后吧每一个Dish转换为DishDTO,并且添加到集合中
        List<DishDto> dishDtoList = new ArrayList<>();
        for (Dish dish : pageInfo.getList()) {
            DishDto dishDto = new DishDto();
            //把dish的属性值拷贝到dishDto里面.
            //什么时候可以使用属性拷贝： 两个对象的属性名与类型都一致的情况下，那么就可以拷贝,如果不对应的属性则不拷贝
            BeanUtils.copyProperties(dish, dishDto);
            //根据菜品的类别id查找类别
            Category category = categoryMapper.findById(dish.getCategoryId());

            dishDto.setCategoryName(category.getName());
            dishDtoList.add(dishDto);
        }

//       5. 自己封装Page对象
        Page<DishDto> pageResult = new Page<>(dishDtoList, pageInfo.getTotal(), pageSize, page);

        return pageResult;
    }

    /**
     * 作用：根据id查找菜品和菜品的口味
     *
     * @param id 菜品的id
     * @return
     */
    @Override
    public DishDto findById(Long id) {
        //根据id查找菜品
        Dish dish = dishMapper.findById(id);
        //根据id查找菜品的口味
        List<DishFlavor> dishFlavorList = dishFlavorMapper.findByDishId(id);
        //创建DishDto， 把菜品和口味封装到DishDto中
        DishDto dishDto = new DishDto();
        //拷贝属性
        BeanUtils.copyProperties(dish, dishDto);
        dishDto.setFlavors(dishFlavorList);

        return dishDto;
    }

    //修改菜品信息
    @Override
    @Transactional//添加事务管理
    public void updateWithFlavor(DishDto dishDto) {
        //补全修改时间
        dishDto.setUpdateTime(LocalDateTime.now());
        //修改菜品
        dishMapper.updateById(dishDto);
        //删除原有菜品口味信息
        dishFlavorMapper.deleteByDishId(dishDto.getId());
        //补全菜品口味并重新插入
        List<DishFlavor> flavors = dishDto.getFlavors();
        List<DishFlavor> collect = flavors.stream().map((flavor -> {
            //补充元素加工
            flavor.setDishId(dishDto.getId());
            flavor.setUpdateUser(dishDto.getUpdateUser());
            flavor.setCreateUser(dishDto.getCreateUser());
            flavor.setCreateTime(LocalDateTime.now());
            flavor.setUpdateTime(LocalDateTime.now());
            return flavor;
        })).collect(Collectors.toList());
        //批量保存菜品口味信息
        dishFlavorMapper.saveBatch(collect);
        //菜品发生变化，需要修改菜品
        Set keys = redisTemplate.keys("dish_*");
        redisTemplate.delete(keys);
    }

    //根据菜品类别id查询菜品
    @Override
    public List<DishDto> findBycateoryId(Long categoryId, Integer status) {
        List<DishDto> dishDtoList = null;
        ValueOperations valueOperations = redisTemplate.opsForValue();
        String key = "dish_" + categoryId + "_" + status;
        dishDtoList = (List<DishDto>) valueOperations.get(key);
        if (dishDtoList == null) {
            List<Dish> dishList = dishMapper.findBycategoryId(categoryId, status);
            //遍历所有dish，转换为Dto
            dishDtoList = dishList.stream().map(dish -> {
                DishDto dishDto = new DishDto();
                //属性拷贝
                BeanUtils.copyProperties(dish, dishDto);
                //查看菜品口味信息
                List<DishFlavor> dishFlavorList = dishFlavorMapper.findByDishId(dish.getId());
                dishDto.setFlavors(dishFlavorList);
                //类别信息
                Category category = categoryMapper.findById(dish.getCategoryId());
                dishDto.setCategoryName(category.getName());
                return dishDto;
            }).collect(Collectors.toList());
            //菜品从数据库中取出来，需要添加缓存，设置保存1天
            valueOperations.set(key,dishDtoList,1, TimeUnit.DAYS);

        }
        return dishDtoList;
    }

    /*根据id批量*/
    @Override
    public void DeleteByIds(List<Long> ids) {
        //判断该菜品是否有在售菜品
        Long count = dishMapper.queryWithStatus(ids);
        if (count > 0) {
            throw new CustomException("该商品存在在售状态，不能删除");
        }
        //如果选中的都是停售，则可以删除
        dishMapper.DeleteByIds(ids);
    }

    /*根据id批量停售*/
    @Override
    public void updateStatusByIds(List<Long> ids, Integer status) {
        dishMapper.updateStatusByIds(ids, status);
    }

}
